#include "StdAfx.h"

#include <MyControls/Splitters.h>
#include <MyControls/Frame.h>
#include <MyControls/Constants.h>
#include "Resource.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

namespace My {

// RightSplitter

RightSplitter::RightSplitter(Frame & f) : m_Frame(f)
{
	m_Frame.Add(this);
}

CRect RightSplitter::Bounds() const
{
	CRect r = m_Frame.GetClientRect();
	if (m_Frame.m_StatusBar.m_hWnd != 0 && m_Frame.m_StatusBar.GetStyle() & WS_VISIBLE)
		r.bottom -= StatusHeight;
	if (m_Frame.m_BottomBar.Visible())
		r.bottom -= m_Frame.m_BottomSplit;
	r.bottom -= SplitterSize;
	if (m_Frame.m_RightBar.Visible())
		r.right -= m_Frame.m_RightSplit;
	r.left = r.right - SplitterSize;
	return r;
}

void RightSplitter::HandlePaint(CDC * pDC, const CRect & r)
{
	CBrush face(My::MeanSysColor(COLOR_BTNFACE, COLOR_BTNSHADOW));
	pDC->FillRect(&r, &face);
	CPen light(PS_SOLID, 1, ::GetSysColor(COLOR_BTNFACE));
	CPen * pOldPen = pDC->SelectObject(&light);
	pDC->MoveTo(0, 0);
	pDC->LineTo(0, Height());
	pDC->SelectObject(pOldPen);
}

bool RightSplitter::HandleDragStart(unsigned int flags, const CPoint & p0, const CPoint & p)
{
	m_Start = m_Frame.m_RightBar.Visible() ? 
		m_Frame.m_RightSplit : 0;
	m_Pos = ClientToScreen(p0).x;
	return true;
}

void RightSplitter::HandleDragEnd(unsigned int flags, const CPoint & p)
{
}

void RightSplitter::HandleDragging(unsigned int flags, const CPoint & p)
{
	int value = m_Start + m_Pos - ClientToScreen(p).x;
	m_Frame.m_RightAutoHide = false;
	if (value < Gap)
		m_Frame.SetSplit(m_Start, m_Frame.m_BottomSplit, false, m_Frame.m_BottomVisible);
	else
		m_Frame.SetSplit(value, m_Frame.m_BottomSplit, true, m_Frame.m_BottomVisible);
}

bool RightSplitter::HandleCursor(unsigned int flags, const CPoint & p)
{
	::SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
	return true;
}

// BottomSplitter

BottomSplitter::BottomSplitter(Frame & f) : m_Frame(f)
{
	m_Frame.Add(this);
}

CRect BottomSplitter::Bounds() const
{
	CRect r = m_Frame.GetClientRect();
	if (m_Frame.m_StatusBar.m_hWnd != 0 && m_Frame.m_StatusBar.GetStyle() & WS_VISIBLE)
		r.bottom -= StatusHeight;
	if (m_Frame.m_BottomBar.Visible())
		r.bottom -= m_Frame.m_BottomSplit;
	r.top = r.bottom - SplitterSize;
	return r;
}

void BottomSplitter::HandlePaint(CDC * pDC, const CRect & r)
{
	CBrush face(My::MeanSysColor(COLOR_BTNFACE, COLOR_BTNSHADOW));
	pDC->FillRect(&r, &face);
	CPen light(PS_SOLID, 1, ::GetSysColor(COLOR_BTNFACE));
	CPen * pOldPen = pDC->SelectObject(&light);
	pDC->MoveTo(0, 0);
	pDC->LineTo(Width(), 0);
	pDC->SelectObject(pOldPen);
}

bool BottomSplitter::HandleDragStart(unsigned int flags, const CPoint & p0, const CPoint & p)
{
	m_Start = m_Frame.m_BottomBar.Visible() ? 
		m_Frame.m_BottomSplit : 0;
	m_Pos = ClientToScreen(p0).y;
	return true;
}

void BottomSplitter::HandleDragEnd(unsigned int flags, const CPoint & p)
{
}

void BottomSplitter::HandleDragging(unsigned int flags, const CPoint & p)
{
	int value = m_Start + m_Pos - ClientToScreen(p).y;
	m_Frame.m_BottomAutoHide = false;
	if (value < Gap)
		m_Frame.SetSplit(m_Frame.m_RightSplit, m_Start, m_Frame.m_RightVisible, false);
	else
		m_Frame.SetSplit(m_Frame.m_RightSplit, value, m_Frame.m_RightVisible, true);
}

bool BottomSplitter::HandleCursor(unsigned int flags, const CPoint & p)
{
	::SetCursor(::LoadCursor(NULL, IDC_SIZENS));
	return true;
}

// CornerGrip

CornerGrip::CornerGrip(Frame & f) : m_Frame(f)
{
	m_Frame.Add(this);
	m_Glyph.Load("CornerGrip", "CornerGripMask");
	m_GlyphUp.Load("CornerGripUp", "CornerGripMask");
}

CRect CornerGrip::Bounds() const
{
	CRect r = m_Frame.GetClientRect();
	if (m_Frame.IsStatusBarVisible())
		r.bottom -= StatusHeight;
	if (m_Frame.m_BottomBar.Visible())
		r.bottom -= m_Frame.m_BottomSplit;
	if (m_Frame.m_RightBar.Visible())
		r.right -= m_Frame.m_RightSplit;
	r.left = r.right - 15;
	r.top = r.bottom - 15;
	return r;
}

void CornerGrip::HandlePaint(CDC * pDC, const CRect & r)
{
	bool down = !m_Frame.m_RightBar.Visible() && !m_Frame.m_BottomBar.Visible();
	if (down)
		m_GlyphUp.Draw(pDC, 0, 0);
	else
		m_Glyph.Draw(pDC, 0, 0);
}

void CornerGrip::HandleLeftUp(unsigned int flags, const CPoint & p)
{
	if (!Dragging()) {
		bool down = !m_Frame.m_RightVisible && !m_Frame.m_BottomVisible;
		m_Frame.SetSplit(m_Frame.m_RightSplit, m_Frame.m_BottomSplit, down, down);
	}
	Control::HandleLeftUp(flags, p);
}

bool CornerGrip::HandleDragStart(unsigned int flags, const CPoint & p0, const CPoint & p)
{
	m_Start.x = m_Frame.m_RightVisible ? 
		m_Frame.m_RightSplit : 0;
	m_Start.y = m_Frame.m_BottomVisible ? 
		m_Frame.m_BottomSplit : 0;
	m_Pos = ClientToScreen(p0);
	CPoint dp = p - p0;
	return fabs(double(dp.x)) + fabs(double(dp.y)) > 2;
}

void CornerGrip::HandleDragEnd(unsigned int flags, const CPoint & p)
{
}

void CornerGrip::HandleDragging(unsigned int flags, const CPoint & p)
{
	CPoint value = m_Start + m_Pos - ClientToScreen(p);
	m_Frame.m_RightAutoHide = false;
	m_Frame.m_BottomAutoHide = false;
	CPoint split = value;
	bool rVisible, bVisible;
	if (value.x < Gap) {
		rVisible = false;
		split.x = m_Start.x;
	} else 
		rVisible = true;

	if (value.y < Gap) {
		bVisible = false;
		split.y = m_Start.y;
	} else
		bVisible = true;

	m_Frame.SetSplit(split.x, split.y, rVisible, bVisible);
}

bool CornerGrip::HandleCursor(unsigned int flags, const CPoint & p)
{
	::SetCursor(::LoadCursor(NULL, IDC_SIZENWSE));
	return true;
}

// RightGrip

RightGrip::RightGrip(Frame & f) : m_Frame(f)
{
	m_Frame.Add(this);
	m_Glyph.Load("RightGrip");
	m_GlyphBack.Load("RightGripBack");
}

CRect RightGrip::Bounds() const
{
	CRect r = m_Frame.m_RightSplitter.Bounds();
	if (r.Height() < 51)
		r.top = r.bottom = r.CenterPoint().y;
	else {
		r.top = r.CenterPoint().y - 10;
		r.bottom = r.top + 21;
	}
	return r;
}

void RightGrip::HandlePaint(CDC * pDC, const CRect & r)
{
	bool back = !m_Frame.m_RightBar.Visible();
	if (back)
		m_GlyphBack.Draw(pDC, 0, 0);
	else
		m_Glyph.Draw(pDC, 0, 0);
}

void RightGrip::HandleLeftUp(unsigned int flags, const CPoint & p)
{
	if (!Dragging())
		m_Frame.SetSplit(m_Frame.m_RightSplit, m_Frame.m_BottomSplit, !m_Frame.m_RightVisible, m_Frame.m_BottomVisible);
	Control::HandleLeftUp(flags, p);
}

bool RightGrip::HandleDragStart(unsigned int flags, const CPoint & p0, const CPoint & p)
{
	m_Start = m_Frame.m_RightVisible ? 
		m_Frame.m_RightSplit : 0;
	m_Pos = ClientToScreen(p0).x;
	CPoint dp = p - p0;
	return fabs(double(dp.x)) + fabs(double(dp.y)) > 2;
}

void RightGrip::HandleDragEnd(unsigned int flags, const CPoint & p)
{
}

void RightGrip::HandleDragging(unsigned int flags, const CPoint & p)
{
	int value = m_Start + m_Pos - ClientToScreen(p).x;
	m_Frame.m_RightAutoHide = false;
	if (value < Gap)
		m_Frame.SetSplit(m_Start, m_Frame.m_BottomSplit, false, m_Frame.m_BottomVisible);
	else
		m_Frame.SetSplit(value, m_Frame.m_BottomSplit, true, m_Frame.m_BottomVisible);
}

bool RightGrip::HandleCursor(unsigned int flags, const CPoint & p)
{
	::SetCursor(::LoadCursor(NULL, IDC_SIZEWE));
	return true;
}

// BottomGrip

BottomGrip::BottomGrip(Frame & f) : m_Frame(f)
{
	m_Frame.Add(this);
	m_Glyph.Load("BottomGrip");
	m_GlyphBack.Load("BottomGripBack");
}

CRect BottomGrip::Bounds() const
{
	CRect r = m_Frame.m_BottomSplitter.Bounds();
	if (m_Frame.m_RightVisible)
		r.right -= m_Frame.m_RightSplit;
	r.right -= SplitterSize;
	if (r.Width() < 51)
		r.left = r.right = r.CenterPoint().x;
	else {
		r.left = r.CenterPoint().x - 10;
		r.right = r.left + 21;
	}
	return r;
}

void BottomGrip::HandlePaint(CDC * pDC, const CRect & r)
{
	bool back = !m_Frame.m_BottomVisible;
	if (back)
		m_GlyphBack.Draw(pDC, 0, 0);
	else
		m_Glyph.Draw(pDC, 0, 0);
}

void BottomGrip::HandleLeftUp(unsigned int flags, const CPoint & p)
{
	if (!Dragging())
		m_Frame.SetSplit(m_Frame.m_RightSplit, m_Frame.m_BottomSplit, m_Frame.m_RightVisible, !m_Frame.m_BottomVisible);
	Control::HandleLeftUp(flags, p);
}

bool BottomGrip::HandleDragStart(unsigned int flags, const CPoint & p0, const CPoint & p)
{
	m_Start = m_Frame.m_BottomVisible ? 
		m_Frame.m_BottomSplit : 0;
	m_Pos = ClientToScreen(p0).y;
	CPoint dp = p - p0;
	return fabs(double(dp.x)) + fabs(double(dp.y)) > 2;
}

void BottomGrip::HandleDragEnd(unsigned int flags, const CPoint & p)
{
}

void BottomGrip::HandleDragging(unsigned int flags, const CPoint & p)
{
	int value = m_Start + m_Pos - ClientToScreen(p).y;
	m_Frame.m_BottomAutoHide = false;
	if (value < Gap)
		m_Frame.SetSplit(m_Frame.m_RightSplit, m_Start, m_Frame.m_RightVisible, false);
	else
		m_Frame.SetSplit(m_Frame.m_RightSplit, value, m_Frame.m_RightVisible, true);
}

bool BottomGrip::HandleCursor(unsigned int flags, const CPoint & p)
{
	::SetCursor(::LoadCursor(NULL, IDC_SIZENS));
	return true;
}

} // My
